package com.buoy.base.aluminumpricespider.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.buoy.base.aluminumpricespider.config.ApiProperties;
import com.buoy.base.aluminumpricespider.config.SpiderProperties;
import com.buoy.base.aluminumpricespider.exception.InvalidParamException;
import com.buoy.base.aluminumpricespider.exception.NotFoundException;
import com.buoy.base.aluminumpricespider.mapper.BaseMetalPriceMapper;
import com.buoy.base.aluminumpricespider.model.BaseMetalPrice;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.time.LocalDate;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
@Slf4j
public class PriceService {
    
    private final BaseMetalPriceMapper baseMetalPriceMapper;
    private final RestTemplate restTemplate;
    private final SpiderProperties spiderProperties;
    private final ApiProperties apiProperties;
    private final SpiderService spiderService;
    
    @Autowired
    public PriceService(BaseMetalPriceMapper baseMetalPriceMapper, 
                        SpiderProperties spiderProperties,
                        ApiProperties apiProperties,
                        @Lazy SpiderService spiderService) {
        this.baseMetalPriceMapper = baseMetalPriceMapper;
        this.spiderProperties = spiderProperties;
        this.apiProperties = apiProperties;
        this.spiderService = spiderService;
        this.restTemplate = new RestTemplate();
    }
    
    /**
     * 保存或更新价格数据
     * 
     * @param baseMetalPrice 价格数据
     * @return 保存或更新后的价格数据
     */
    public BaseMetalPrice saveOrUpdatePrice(BaseMetalPrice baseMetalPrice) {
        if (baseMetalPrice == null) {
            throw new InvalidParamException("价格数据不能为空");
        }
        
        // 检查数据库中是否已存在当日记录
        BaseMetalPrice existingPrice = baseMetalPriceMapper
                .findByPriceDateAndPriceSource(baseMetalPrice.getPriceDate(), baseMetalPrice.getPriceSource());
        
        if (existingPrice != null) {
            baseMetalPrice.setId(existingPrice.getId());
            log.info("更新{}铝价记录，id: {}", 
                    baseMetalPrice.getPriceSource().equals(spiderProperties.getShanghaiPriceSource()) ? "上海" : "长江", 
                    baseMetalPrice.getId());
            baseMetalPriceMapper.updateById(baseMetalPrice);
        } else {
            log.info("创建新的{}铝价记录", 
                    baseMetalPrice.getPriceSource().equals(spiderProperties.getShanghaiPriceSource()) ? "上海" : "长江");
            baseMetalPriceMapper.insert(baseMetalPrice);
        }
        
        // 推送到系统
        // pushToMind(baseMetalPrice);
        
        return baseMetalPrice;
    }
    
    /**
     * 手动更新铝价
     *
     * @param priceSource  价格来源 ("shanghai" 或 "changjiang")
     * @param averagePrice 平均价格
     * @param priceDate    价格日期
     * @return 更新后的铝价数据
     */
    public BaseMetalPrice updatePrice(String priceSource, int averagePrice, LocalDate priceDate) {
        if (priceSource == null || averagePrice <= 0 || priceDate == null) {
            throw new InvalidParamException("价格来源、价格和日期不能为空");
        }

        if (!priceSource.equals(spiderProperties.getShanghaiPriceSource()) && 
            !priceSource.equals(spiderProperties.getChangjiangPriceSource())) {
            throw new InvalidParamException("价格来源必须是 'shanghai' 或 'changjiang'");
        }

        BaseMetalPrice baseMetalPrice = new BaseMetalPrice();
        baseMetalPrice.setPriceSource(priceSource);
        baseMetalPrice.setPriceDate(priceDate);
        baseMetalPrice.setAveragePrice(averagePrice);
        baseMetalPrice.setManualUpdate(1);
        
        return saveOrUpdatePrice(baseMetalPrice);
    }
    
    /**
     * 将价格推送到指定系统
     *
     * @param baseMetalPrice 铝价数据
     */
    public void pushToMind(BaseMetalPrice baseMetalPrice) {
        String url = apiProperties.getMind().getUrl() + "?password=" + apiProperties.getMind().getPassword();

        // 创建请求头
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);

        // 创建请求体
        Map<String, Object> requestBody = new HashMap<>();
        requestBody.put("averagePrice", baseMetalPrice.getAveragePrice());
        requestBody.put("priceDate", baseMetalPrice.getPriceDate().toString()); // 铝价日期 格式为：yyyy-MM-dd
        requestBody.put("priceSource", baseMetalPrice.getPriceSource()); // 铝价来源 长江铝价：changjiang 上海铝价：shanghai

        HttpEntity<Map<String, Object>> requestEntity = new HttpEntity<>(requestBody, headers);

        try {
            // 发送 POST 请求
            ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.POST, requestEntity, String.class);
            log.info("推送铝价数据成功，响应状态: {}", response.getStatusCode());
        } catch (Exception e) {
            log.error("推送铝价数据失败: {}", e.getMessage(), e);
        }
    }
    
    /**
     * 分页查询铝价数据
     * @param pageNum 页码（从0开始）
     * @param pageSize 每页大小
     * @param source 价格来源（可选）
     * @param startDate 开始日期（可选）
     * @param endDate 结束日期（可选）
     * @param manualUpdate 是否手动更新（可选）
     * @return 分页数据
     */
    public Page<BaseMetalPrice> getPrices(int pageNum, int pageSize, String source, LocalDate startDate, LocalDate endDate, String manualUpdate) {
        log.debug("查询铝价数据，页码: {}, 大小: {}, 来源: {}, 开始日期: {}, 结束日期: {}, 手动更新: {}", 
                pageNum, pageSize, source, startDate, endDate, manualUpdate);
        
        // 创建MyBatis-Plus的Page对象，页码从1开始，需要+1
        Page<BaseMetalPrice> page = new Page<>(pageNum + 1, pageSize);
        
        // 构建查询条件
        LambdaQueryWrapper<BaseMetalPrice> queryWrapper = new LambdaQueryWrapper<>();
        
        // 添加条件
        if (source != null && !source.isEmpty()) {
            queryWrapper.eq(BaseMetalPrice::getPriceSource, source);
        }
        
        if (startDate != null) {
            queryWrapper.ge(BaseMetalPrice::getPriceDate, startDate);
        }
        
        if (endDate != null) {
            queryWrapper.le(BaseMetalPrice::getPriceDate, endDate);
        }
        
        if (manualUpdate != null && !manualUpdate.trim().isEmpty()) {
            try {
                queryWrapper.eq(BaseMetalPrice::getManualUpdate, Integer.parseInt(manualUpdate));
            } catch (NumberFormatException e) {
                throw new InvalidParamException("手动更新参数必须是数字");
            }
        }
        
        // 按日期降序排序
        queryWrapper.orderByDesc(BaseMetalPrice::getPriceDate);
        
        // 执行查询
        return baseMetalPriceMapper.selectPage(page, queryWrapper);
    }
    
    /**
     * 删除铝价记录
     * @param id 记录ID
     */
    public void deletePrice(Long id) {
        log.debug("删除铝价记录，ID: {}", id);
        BaseMetalPrice price = baseMetalPriceMapper.selectById(id);
        if (price == null) {
            throw new NotFoundException("铝价记录", id);
        }
        baseMetalPriceMapper.deleteById(id);
    }
    
    /**
     * 根据ID获取铝价记录
     * @param id 记录ID
     * @return 铝价记录
     */
    public BaseMetalPrice getPriceById(Long id) {
        BaseMetalPrice price = baseMetalPriceMapper.selectById(id);
        if (price == null) {
            throw new NotFoundException("铝价记录", id);
        }
        return price;
    }
    
    /**
     * 获取指定价格来源和日期的前N天的平均价格
     * 
     * @param priceSource 价格来源 ("shanghai" 或 "changjiang")
     * @param priceDate 价格日期
     * @param days 天数
     * @return 平均价格，如果数据不足则返回null
     */
    public Integer getPreviousDaysAvgPrice(String priceSource, LocalDate priceDate, int days) {
        if (priceSource == null || priceDate == null || days <= 0) {
            throw new InvalidParamException("价格来源、日期和天数不能为空或无效");
        }
        
        if (!priceSource.equals(spiderProperties.getShanghaiPriceSource()) && 
            !priceSource.equals(spiderProperties.getChangjiangPriceSource())) {
            throw new InvalidParamException("价格来源必须是 'shanghai' 或 'changjiang'");
        }
        
        // 查询前N天的价格数据
        List<BaseMetalPrice> previousPrices = baseMetalPriceMapper.findPreviousDaysPrices(priceSource, priceDate, days);
        
        // 检查是否有足够的数据
        if (previousPrices.size() < days) {
            log.warn("{}前{}天的数据不足，只有{}条记录", 
                    priceSource.equals(spiderProperties.getShanghaiPriceSource()) ? "上海铝价" : "长江铝价", 
                    days, previousPrices.size());
            return null;
        }
        
        // 计算平均价格
        int sum = previousPrices.stream()
                .mapToInt(BaseMetalPrice::getAveragePrice)
                .sum();
        
        return sum / days;
    }
    
    /**
     * 获取指定价格记录的前三天均价
     * 
     * @param baseMetalPrice 价格记录
     * @return 填充了前三天均价的价格记录
     */
    public BaseMetalPrice calculateThreeDayAvgPrice(BaseMetalPrice baseMetalPrice) {
        if (baseMetalPrice == null) {
            throw new InvalidParamException("价格记录不能为空");
        }
        
        try {
            // 先尝试从网页获取前三天均价
            Integer threeDayAvg = null;
            if (baseMetalPrice.getPriceSource().equals(spiderProperties.getShanghaiPriceSource())) {
                threeDayAvg = spiderService.getShanghaiThreeDayAvgPrice();
            } else if (baseMetalPrice.getPriceSource().equals(spiderProperties.getChangjiangPriceSource())) {
                threeDayAvg = spiderService.getChangjiangThreeDayAvgPrice(baseMetalPrice.getPriceDate());
            }
            
            // 如果从网页获取失败，则从数据库计算
            if (threeDayAvg == null) {
                log.info("从网页获取{}的前三天均价失败，尝试从数据库计算", baseMetalPrice.getPriceDate());
                threeDayAvg = getPreviousDaysAvgPrice(
                        baseMetalPrice.getPriceSource(), 
                        baseMetalPrice.getPriceDate(), 
                        3);
            }
            
            baseMetalPrice.setThreeDayAvgPrice(threeDayAvg);
            return baseMetalPrice;
        } catch (Exception e) {
            log.error("计算前三天均价出错: {}", e.getMessage(), e);
            return baseMetalPrice;
        }
    }
    
    /**
     * 获取指定价格记录的前五天均价
     * 
     * @param baseMetalPrice 价格记录
     * @return 填充了前五天均价的价格记录
     */
    public BaseMetalPrice calculateFiveDayAvgPrice(BaseMetalPrice baseMetalPrice) {
        if (baseMetalPrice == null) {
            throw new InvalidParamException("价格记录不能为空");
        }
        
        try {
            // 先尝试从网页获取前五天均价
            Integer fiveDayAvg = null;
            if (baseMetalPrice.getPriceSource().equals(spiderProperties.getShanghaiPriceSource())) {
                fiveDayAvg = spiderService.getShanghaiFiveDayAvgPrice();
            } else if (baseMetalPrice.getPriceSource().equals(spiderProperties.getChangjiangPriceSource())) {
                fiveDayAvg = spiderService.getChangjiangFiveDayAvgPrice(baseMetalPrice.getPriceDate());
            }
            
            // 如果从网页获取失败，则从数据库计算
            if (fiveDayAvg == null) {
                log.info("从网页获取{}的前五天均价失败，尝试从数据库计算", baseMetalPrice.getPriceDate());
                fiveDayAvg = getPreviousDaysAvgPrice(
                        baseMetalPrice.getPriceSource(), 
                        baseMetalPrice.getPriceDate(), 
                        5);
            }
            
            baseMetalPrice.setFiveDayAvgPrice(fiveDayAvg);
            return baseMetalPrice;
        } catch (Exception e) {
            log.error("计算前五天均价出错: {}", e.getMessage(), e);
            return baseMetalPrice;
        }
    }
} 